package comp353Games;

/**
 * Clobber.java describes the rules for a game of Clobber.
 *
 * @author Tyler Radley, Andre Harvey, Deanna Fink
 * @version 4/30/12
 */
public class Clobber implements GameModel {

    //A 2 dimensional board containing the clobber pieces.
    private int[][] clobberBoard;
    // number of columns the clobberBoard uses.
    private int cols;
    // number of rows the clobberBoard uses
    private int rows;

    /**
     * Constructor for a game with the default row and column parameters
     */
    public Clobber() {
        // initialize instance variables
        this.cols = 5;
        this.rows = 6;
        this.clobberBoard = new int[rows][cols];
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                clobberBoard[i][j] = (int) Math.pow(-1, j + i);
            }
        }
    }

    /**
     * Constructor for a game with a given setup.
     *
     * @param clobberBoard Contents of the boxes.
     */
    public Clobber(int[][] clobberBoard) {
        // initialize instance variables
        this.rows = clobberBoard.length;
        this.cols = clobberBoard[0].length;
        this.clobberBoard = new int[rows][cols];
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                this.clobberBoard[i][j] = clobberBoard[i][j];
            }
        }
    }
    /**
     * Returns the number of columns in this game
     *
     * @return the number of columns in the game
     */
    public int getColumns() {
        return this.cols;
    }

    /**
     * Returns the number of rows in this game
     *
     * @return the number of rows in the game
     */
    public int getRows() {
        return this.rows;
    }

    @Override
    public String getName() {
        return "Clobber";
    }

    @Override
    public Clobber getNewGame() {
        return new Clobber();
    }

    @Override
    public ClobberDisplay getDisplay(GameModel game) {
        return new ClobberDisplay(game);
    }

    @Override
    public String[] getInstructions(int currentPlayer) {
        String[] instructions = new String[3];
        if (currentPlayer == 1) {
            instructions[2] = "RED";
        } else {
            instructions[2] = "BLACK";
        }
        instructions[0] = "Welcome to Clobber!  ";
        instructions[1] = "It's now " + instructions[2] + "'s turn.  Drag one of your game pieces to an adjacent enemy piece to clobber it.";

        return instructions;
    }

    /**
     * Retrieves a clone of the clobber board
     *
     * @return a clone of the clobber board
     */
    public int[][] getClobberBoard() {
        int[][] clobberBoardClone = new int[rows][cols];
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                clobberBoardClone[i][j] = clobberBoard[i][j];
            }
        }
        return clobberBoardClone;
    }

    @Override
    public Clobber updateGame(int[] press, int[] release, int[] click, int currentPlayer) {
        clobberBoard[release[0]][release[1]] = clobberBoard[press[0]][press[1]];
        clobberBoard[press[0]][press[1]] = 0;
        return new Clobber(clobberBoard);
    }

    @Override
    public boolean validMove(int[] clobberPress, int[] clobberRelease, int[] click, int currentPlayer) {
        int player = 1;
        if (currentPlayer == 2) {
            player = -1;
        }
        if (clobberBoard[clobberPress[0]][clobberPress[1]] == player && clobberBoard[clobberRelease[0]][clobberRelease[1]] == player * -1
                && ((clobberPress[1] == clobberRelease[1] && clobberPress[0] == clobberRelease[0] + 1)
                || (clobberPress[1] == clobberRelease[1] && clobberPress[0] == clobberRelease[0] - 1)
                || (clobberPress[0] == clobberRelease[0] && clobberPress[1] == clobberRelease[1] + 1)
                || (clobberPress[0] == clobberRelease[0] && clobberPress[1] == clobberRelease[1] - 1))) {
            return true;
        }
        return false;
    }

    @Override
    public int[] mousePressedHandler(int xPosition, int yPosition) {
        System.out.println(xPosition + "," + yPosition);
        int[] clobPress = new int[2];
        int rowIndex;
        int columnIndex;
        int[] yBounds = new int[rows];
        int[] xBounds = new int[cols];
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                xBounds[j] = j * 40 + 133;
                yBounds[i] = i * 40 + 17;
                if (xPosition > xBounds[j] && xPosition < xBounds[j] + 30 && yPosition > yBounds[i] && yPosition < yBounds[i] + 30) {
                    rowIndex = (int) (Math.floor((yPosition - 17) / 40));
                    columnIndex = (int) (Math.floor((xPosition - 133) / 40));
                    clobPress[0] = rowIndex;
                    clobPress[1] = columnIndex;
                    return clobPress;
                }
            }
        }
        return clobPress;
    }

    @Override
    public int[] mouseReleasedHandler(int xPosition, int yPosition) {
        int[] clobRelease = new int[2];
        int rowIndex;
        int columnIndex;
        int[] yBounds = new int[rows];
        int[] xBounds = new int[cols];
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                xBounds[j] = j * 40 + 133;
                yBounds[i] = i * 40 + 17;
                if (xPosition > xBounds[j] && xPosition < xBounds[j] + 30 && yPosition > yBounds[i] && yPosition < yBounds[i] + 30) {
                    rowIndex = (int) (Math.floor((yPosition - 17) / 40));
                    columnIndex = (int) (Math.floor((xPosition - 133) / 40));
                    clobRelease[0] = rowIndex;
                    clobRelease[1] = columnIndex;
                    return clobRelease;
                }
            }
        }
        return clobRelease;
    }

    @Override
    public boolean hasMovesRemaining(int currentPlayer) {
        int player = 1;
        if (currentPlayer == 2) {
            player = -1;
        }
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                if (clobberBoard[i][j] == player) {
                    if (this.hasMoveDown(player, i, j)
                            || this.hasMoveUp(player, i, j)
                            || this.hasMoveToLeft(player, i, j)
                            || this.hasMoveToRight(player, i, j)) {
                        return true;
                    }
                }
            }
        }
        return false;
    }

    /**
     * Tells whether or not the player is able to move a piece to the left from
     * a particular position
     *
     * @param player the player that will move
     * @param rowPosition the row that the player will move from
     * @param columnPosition the column that the player will move from
     * @return Whether or not the player can move
     */
    public boolean hasMoveToLeft(int player, int rowPosition, int columnPosition) {
        if (rowPosition == 0) {
            return false;
        }
        return (this.clobberBoard[rowPosition - 1][columnPosition] == player * -1);

    }

    /**
     * Tells whether or not the player is able to move a piece to the right from
     * a particular position
     *
     * @param player the player that will move
     * @param rowPosition the row that the player will move from
     * @param columnPosition the column that the player will move from
     * @return Whether or not the player can move
     */
    public boolean hasMoveToRight(int player, int rowPosition, int columnPosition) {
        if (rowPosition == rows - 1) {
            return false;
        }
        return (this.clobberBoard[rowPosition + 1][columnPosition] == player * -1);

    }

    /**
     * Tells whether or not the player is able to move a piece up from a
     * particular position
     *
     * @param player the player that will move
     * @param rowPosition the row that the player will move from
     * @param columnPosition the column that the player will move from
     * @return Whether or not the player can move
     */
    public boolean hasMoveUp(int player, int rowPosition, int columnPosition) {
        if (columnPosition == 0) {
            return false;
        }
        return (this.clobberBoard[rowPosition][columnPosition - 1] == player * -1);
    }

    /**
     * Tells whether or not the player is able to move a piece down from a
     * particular position
     *
     * @param player the player that will move
     * @param rowPosition the row that the player will move from
     * @param columnPosition the column that the player will move from
     * @return Whether or not the player can move
     */
    public boolean hasMoveDown(int player, int rowPosition, int columnPosition) {
        if (columnPosition == cols - 1) {
            return false;
        }
        return (this.clobberBoard[rowPosition][columnPosition + 1] == player * -1);
    }

    @Override
    public int[] mouseClickedHandler(int xPosition, int yPosition, int currentPlayer) {
        return null;
    }

    @Override
    public String save() {
        String saveText = "<Clobber>\n";
        saveText += "<clobberBoard>\n";
        saveText += rows + "x" + cols + "y";
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                saveText += clobberBoard[i][j] + ".";
            }
            saveText += "\n";
        }
        saveText += "</clobberBoard>\n";
        saveText += "<Clobber>";
        return saveText;

    }

    @Override
    public Clobber load(String fileString) {
        int index = 23;

        String xString = "";
        String yString = "";


        while (fileString.substring(index, index + 1).equals("x") == false) {
            xString += fileString.charAt(index);
            index++;
        }
        index++;
        
        while (fileString.substring(index, index + 1).equals("y") == false) {
            yString += fileString.charAt(index);
            index++;
        }
        index++;

        int xValue = Integer.parseInt(xString);
        int yValue = Integer.parseInt(yString);


        int[][] board = new int[xValue][yValue];
        for (int i = 0; i < xValue; i++) {
            for (int j = 0; j < yValue; j++) {
                String numberString = "";
                while (fileString.substring(index, index + 1).equals(".") == false) {
                    numberString += fileString.charAt(index);
                    index++;
                }
                board[i][j] = Integer.parseInt(numberString);
                index++;
            }
        }
        return new Clobber(board);
    }
}
